package br.com.sgpv2.controler;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import br.com.sgpv2.entity.cargos.CargoFuncao;
import br.com.sgpv2.entity.dependente.Dependente;
import br.com.sgpv2.entity.dependente.OcupacaoDependenteEnum;
import br.com.sgpv2.entity.dependente.RelacaoParentescoEnum;
import br.com.sgpv2.entity.organograma.Departamento;
import br.com.sgpv2.entity.organograma.Nivel;
import br.com.sgpv2.entity.organograma.Secretaria;
import br.com.sgpv2.entity.pessoa.BancoEnum;
import br.com.sgpv2.entity.pessoa.Contrato;
import br.com.sgpv2.entity.pessoa.GrauEscolaridadeEnum;
import br.com.sgpv2.entity.pessoa.Pessoa;
import br.com.sgpv2.entity.pessoa.PessoaDTO;
import br.com.sgpv2.entity.pessoa.RacaCorEnum;
import br.com.sgpv2.entity.pessoa.TipoDeficienciaEnum;
import br.com.sgpv2.entity.pessoa.endereco.Cidade;
import br.com.sgpv2.entity.pessoa.endereco.Estado;
import br.com.sgpv2.entity.pessoa.endereco.Pais;
import br.com.sgpv2.service.contrato.ContratoService;
import br.com.sgpv2.service.departamento.DepartamentoService;
import br.com.sgpv2.service.dependentes.DependenteService;
import br.com.sgpv2.service.entidade.EntidadeService;
import br.com.sgpv2.service.nivel.NivelService;
import br.com.sgpv2.service.pessoa.PessoaService;
import br.com.sgpv2.service.secretaria.SecretariaService;

/**
 * Handles requests for the application /pessoas.
 */
@Controller
public class PessoaController extends SGPController {
	
	@Autowired
	private PessoaService pessoaService;
	@Autowired
	private DependenteService dependenteService;
	@Autowired
	private ContratoService contratoService;
	
	@Autowired
	private NivelService nivelService;
	@Autowired
	private SecretariaService secretariaService;
	@Autowired
	private DepartamentoService departamentoService;
	@Autowired
	private EntidadeService entidadeService;
	
	/**
	 * Página de pessoas - controller da página pessoas.
	 * @throws Exception.
	 */
	@RequestMapping(value = "/pessoas", method = RequestMethod.GET)
	public String pessoas(Locale locale, Model model) throws Exception {
		
		List<PessoaDTO> pessoas = pessoaService.consultarPessoaDTO();
		configurarPaginacao(pessoas, model);
		
		model.addAttribute("pessoas", getPagedListHolder().getPageList());
		model.addAttribute("pessoaDTO", new PessoaDTO());
		
		return "pessoas";
	}
	
	/**
	 * Página de pessoas - controller da página pessoas.
	 * @throws Exception.
	 */
	@RequestMapping(value = "/pessoas", method = RequestMethod.POST)
	public String pessoas(Locale locale, Model model, @RequestParam String descricao) throws Exception {
		
		List<PessoaDTO> pessoas = pessoaService.consultarPessoasDTOPorFiltro(descricao, null, null);
		configurarPaginacao(pessoas, model);
		
		model.addAttribute("pessoas", getPagedListHolder().getPageList());
		model.addAttribute("pessoaDTO", new PessoaDTO());
		
		return "pessoas";
	}
	
	/**
	 * avança para página de inclusão de pessoas.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/salvar", method = RequestMethod.GET)
	public String getSalvar(Model model) throws Exception {
		model.addAttribute("racaCor",RacaCorEnum.values());
		model.addAttribute("tipoDeficiencia",TipoDeficienciaEnum.values());
		model.addAttribute("grauEscolaridade",GrauEscolaridadeEnum.values());
		model.addAttribute("pessoa",new Pessoa());
		
		model.addAttribute("secretarias",getSecretarias());
		model.addAttribute("departamentos",getDepartamentos());
		model.addAttribute("cargosFuncoes",getCargosFuncoes());
		model.addAttribute("niveis",getNiveis());
		
		
		List<String> paises = new ArrayList<String>();
		List<Pais> paisesBanco = pessoaService.consultarPaises();
		for (Pais pais : paisesBanco) {
			paises.add(pais.getNomePais());
		}		
		
		model.addAttribute("paises",paises);
		return "pessoa_incluir";
	}
	
	private List<Nivel> getNiveis() {
		return pessoaService.getNiveis();
	}

	private List<CargoFuncao> getCargosFuncoes() {
		return pessoaService.getCargosFuncoes();
	}

	private List<Departamento> getDepartamentos() {
		return pessoaService.getDepartamentos();
	}

	private List<Secretaria> getSecretarias() {
		return pessoaService.getSecretarias();
	}

	@ResponseBody  
	@RequestMapping(value = "/pessoa/listar-estados/{pais}", method = RequestMethod.GET)
	public List<Estado> listarEstados(@PathVariable String pais, Model model){
		
		//FIXME RHAS criar consulta para retornar pais pela string.
		Pais paisFake = new Pais();
		paisFake.setId(1);
		paisFake.setNomePais("Brasil");
		paisFake.setSiglaPais("BR");
		
		List<Estado> estadosBanco = pessoaService.consultarEstadosPorPais(paisFake);
				
		return estadosBanco;
	}
	
	@ResponseBody  
	@RequestMapping(value = "/pessoa/listar-cidades/{siglaEstado}", method = RequestMethod.GET)
	public List<Cidade> listarCidades(@PathVariable String siglaEstado, Model model){
		List<Cidade> cidadesBanco = pessoaService.consultarCidadesPorEstado(siglaEstado);				
		return cidadesBanco;
	}
	
	@ResponseBody  
	@RequestMapping(value = "/pessoa/pessoa/listar-cidades/{siglaEstado}", method = RequestMethod.GET)
	public List<Cidade> listarCidadesAlterar(@PathVariable String siglaEstado, Model model){
		List<Cidade> cidadesBanco = pessoaService.consultarCidadesPorEstado(siglaEstado);				
		return cidadesBanco;
	}
	
	/**
	 * avança para página de inclusão de pessoas.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/salvar", method = RequestMethod.POST)
	public String salvar(@ModelAttribute Pessoa pessoa, BindingResult result, Model model) throws Exception {
		
		if(pessoa.getEndereco().getEstadoTransiente() != null){
			Estado estadoBanco = pessoaService.buscarEstadoPorNome(pessoa.getEndereco().getEstadoTransiente());
			pessoa.getEndereco().setEstado(estadoBanco);
		}			
		if(pessoa.getEndereco().getCidadeTransiente() != null){
			Cidade cidadeBanco = pessoaService.buscarCidadePorNome(pessoa.getEndereco().getCidadeTransiente());
			pessoa.getEndereco().setCidade(cidadeBanco);
		}
		
		Pais paisBanco = pessoaService.buscarPaisPorNome(pessoa.getEndereco().getPaisTransiente());
		pessoa.getEndereco().setPais(paisBanco);
				
		if(pessoa != null){
			pessoa.setEntidade(entidadeService.buscarEntidade());
			pessoaService.salvar(pessoa);
		}
		return "redirect:../pessoas";
	}
	
	/**
	 * avança para página de alteração de pessoas.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/alterar/{pk}", method = RequestMethod.GET)
	public String getAlterar(@PathVariable Integer pk, Model model) throws Exception {
		Pessoa pessoaAlteracao = pessoaService.buscar(pk);
		if(pessoaAlteracao != null){
			model.addAttribute("pessoa",pessoaAlteracao);
			model.addAttribute("racaCor",RacaCorEnum.values());
			model.addAttribute("tipoDeficiencia",TipoDeficienciaEnum.values());
			model.addAttribute("grauEscolaridade",GrauEscolaridadeEnum.values());
			
			List<String> paises = new ArrayList<String>();
			List<Pais> paisesBanco = pessoaService.consultarPaises();
			for (Pais pais : paisesBanco) {
				paises.add(pais.getNomePais());
			}		
					
			model.addAttribute("paises",paises);
			model.addAttribute("estados",pessoaService.consultarEstadosPorPais(pessoaAlteracao.getEndereco().getPais()));
			model.addAttribute("cidades",pessoaService.consultarCidadesPorEstado(pessoaAlteracao.getEndereco().getEstado().getSiglaEstado()));
			
			
			model.addAttribute("secretarias",getSecretarias());
			model.addAttribute("departamentos",getDepartamentos());
			model.addAttribute("cargosFuncoes",getCargosFuncoes());
			model.addAttribute("niveis",getNiveis());		
			
			return "pessoa_alterar";
		}else{
			return "redirect:../pessoas";
		}		
	}
	
	/**
	 * avança para página de alteração de pessoas.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/alterar", method = RequestMethod.POST)
	public String alterar(@ModelAttribute Pessoa pessoa, BindingResult result,Model model) throws Exception {
		if(pessoa.getEndereco().getEstadoTransiente() != null){
			Estado estadoBanco = pessoaService.buscarEstadoPorNome(pessoa.getEndereco().getEstadoTransiente());
			pessoa.getEndereco().setEstado(estadoBanco);
		}			
		if(pessoa.getEndereco().getCidadeTransiente() != null){
			Cidade cidadeBanco = pessoaService.buscarCidadePorNome(pessoa.getEndereco().getCidadeTransiente());
			pessoa.getEndereco().setCidade(cidadeBanco);
		}
		
		Pais paisBanco = pessoaService.buscarPaisPorNome(pessoa.getEndereco().getPaisTransiente());
		pessoa.getEndereco().setPais(paisBanco);
			
		if(pessoa != null){
			pessoa.setEntidade(entidadeService.buscarEntidade());
			pessoaService.alterar(pessoa);
		}
		return "redirect:../pessoas";
	}
	
	/**
	 * Exclui uma pessoa.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/excluir/{pk}", method = RequestMethod.GET)
	public String excluir(@PathVariable Integer pk, Model model) throws Exception {
		Pessoa pessoaExclusao = pessoaService.buscar(pk);
		
		if(pessoaExclusao !=null){
			pessoaService.remover(pessoaExclusao);
		}
		
		List<PessoaDTO> listaPessoas = pessoaService.consultarPessoaDTO();
		
		model.addAttribute("pessoas", listaPessoas);
		model.addAttribute("pessoaDTO", new PessoaDTO());
		
		return "redirect:/pessoas";
	}
	
	@RequestMapping(value = "/pessoa/selectEstados", method = RequestMethod.POST)
	public String selectEstados(Model model, HttpServletRequest request) {
	
		model.addAttribute("estados", new ArrayList<Estado>());
		
		return  "pessoa/dropDownEstados";
		
	}
	
	@RequestMapping(value = "/pessoa/selectCidades", method = RequestMethod.POST)
	public String selectCidades(Model model, HttpServletRequest request) {
		
		model.addAttribute("cidades", new ArrayList<Cidade>()); // Mudar para consulta
		
		return  "pessoa/dropDownCidades";
		
	}
	
	@RequestMapping(value = "/pessoa/incluir-dependente/{idPessoa}" , method = RequestMethod.GET)
	public String carregarIncluirDependentes(@PathVariable Integer idPessoa, Model model){
		try {
			Pessoa pessoa = pessoaService.buscar(idPessoa);
			Dependente dependente = new Dependente();
			dependente.setPessoa(pessoa);
			if(pessoa != null){
				carregarModelDependente(dependente, model);
				return "dependentes";
			}			
		} catch (NegocioExeception e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}		
		return "redirect:/pessoas";
	}
	
	@RequestMapping(value = "/pessoa/alterar-dependente/{idDependente}" , method = RequestMethod.GET)
	public String carregarAlterarDependentes(@PathVariable Integer idDependente, Model model){
		try {
			Dependente dependente = dependenteService.buscar(idDependente);
			if(dependente != null){
				carregarModelDependente(dependente, model);
				return "dependentes";
			}			
		} catch (NegocioExeception e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}		
		return "redirect:/pessoas";
	}
	
	private void carregarModelDependente(Dependente dependente, Model model) throws Exception {
		model.addAttribute("relacaoParentesco",RelacaoParentescoEnum.values());
		model.addAttribute("ocupacaoDependente",OcupacaoDependenteEnum.values());
		model.addAttribute("dependente",dependente);
		model.addAttribute("dependentes", dependenteService.consultarPorTitular(dependente.getPessoa()));
	}
	
	@RequestMapping(value = "/pessoa/manter-dependentes", method = RequestMethod.POST)
	public String salvar(@ModelAttribute Dependente dependente, Model model, BindingResult result) throws Exception {
				
		if(dependente != null && dependente.getId() == 0){
			dependenteService.salvar(dependente);
		} else if (dependente != null && dependente.getId() != 0) {
			dependenteService.alterar(dependente);
		}
		return "redirect:../pessoa/incluir-dependente/"+dependente.getPessoa().getId();
	}
	
	/**
	 * Exclui um Dependente.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/excluir_dependente/{pk}", method = RequestMethod.GET)
	public String excluirDependente(@PathVariable Integer pk, Model model) throws Exception {
		Dependente dependenteExclusao = dependenteService.buscar(pk);
		Integer idPessoa = dependenteExclusao.getPessoa().getId();
		
		if(dependenteExclusao !=null){
			dependenteService.remover(dependenteExclusao);
		}
		
		return "redirect:../incluir-dependente/"+idPessoa;
	}
	
	@RequestMapping(value = "/pessoa/incluir-contrato/{idPessoa}" , method = RequestMethod.GET)
	public String carregarIncluirContratos(@PathVariable Integer idPessoa, Model model){
		try {
			Pessoa pessoa = pessoaService.buscar(idPessoa);
			Contrato contrato = new Contrato();
			contrato.setPessoa(pessoa);
			
			if(pessoa != null){
				carregarModelContrato(contrato, model);
				return "contratos";
			}			
		} catch (NegocioExeception e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}		
		return "redirect:/pessoas";
	}
	
	@RequestMapping(value = "/pessoa/alterar-contrato/{idContrato}" , method = RequestMethod.GET)
	public String carregarAlterarContratos(@PathVariable Integer idContrato, Model model){
		try {
			Contrato contrato = contratoService.buscar(idContrato);
			if(contrato != null){
				carregarModelContrato(contrato, model);
				return "contratos";
			}			
		} catch (NegocioExeception e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}		
		return "redirect:/pessoas";
	}
	
	private void carregarModelContrato(Contrato contrato, Model model) throws Exception {
		model.addAttribute("contrato",contrato);
		model.addAttribute("niveis",nivelService.listar());
		model.addAttribute("secretarias",secretariaService.listar());
		model.addAttribute("departamentos",departamentoService.listar());
		model.addAttribute("contratos", contratoService.consultarPorTitular(contrato.getPessoa()));
		model.addAttribute("bancos",BancoEnum.values());
	}
	
	@RequestMapping(value = "/pessoa/manter-contratos", method = RequestMethod.POST)
	public String salvar(@ModelAttribute Contrato contrato, BindingResult result,Model model) throws Exception {
				
		if(contrato != null && contrato.getId() == 0){
			contratoService.salvar(contrato);
		} else if (contrato != null && contrato.getId() != 0) {
			contratoService.alterar(contrato);
		}
		return "redirect:../pessoa/incluir-contrato/"+contrato.getPessoa().getId();
	}
	
	/**
	 * Exclui um Contrato.
	 * @throws Exception 
	 */
	@RequestMapping(value = "/pessoa/excluir_contrato/{pk}", method = RequestMethod.GET)
	public String excluirContrato(@PathVariable Integer pk, Model model) throws Exception {
		Contrato contratoExclusao = contratoService.buscar(pk);
		Integer idPessoa = contratoExclusao.getPessoa().getId();
		
		if(contratoExclusao !=null){
			contratoService.remover(contratoExclusao);
		}
		
		return "redirect:../incluir-contrato/"+idPessoa;
	}
	
	@ResponseBody
	@RequestMapping(value = "/pessoa/paginacao/{acao}", method = RequestMethod.GET)
	public ModelAndView paginacao(@PathVariable String acao, Model model) throws Exception {		
		navegarPaginacao(acao, model);
		model.addAttribute("pessoas", getPagedListHolder().getPageList());
		return new ModelAndView("pessoa.lista");
	}
	

}
